#ifndef __M_CONNECTION_H__
#define __M_CONNECTION_H__

#include "mq_channel.hpp"

namespace wsmq
{
    class Connection
    {
    public:
        using ptr = std::shared_ptr<Connection>;
        Connection(const muduo::net::TcpConnectionPtr& conn,
                   const VirtualHost::ptr& host,
                   const ConsumerManager::ptr& cmp,
                   const ProtobufCodecPtr& codec,
                   const ThreadPool::ptr& pool):
                   _conn(conn), 
                   _host(host),
                   _cmp(cmp),
                   _codec(codec),
                   _pool(pool),
                   _channels(std::make_shared<ChannelManager>())
        {}
        void openChannel(const openChannelRequestPtr& req)
        {
            bool ret = _channels->openChannel(req->cid(), _conn, _host, _cmp, _codec, _pool);
            if (ret == false) {
                DLOG("创建信道的时候，信道ID重复了");
                return basicResponse(req->cid(), req->rid(), ret);
            }
            DLOG("%s 信道创建成功！", req->cid().c_str());
            basicResponse(req->cid(), req->rid(), ret);
        }
        void closeChannel(const closeChannelRequestPtr& req)
        {
            _channels->closeChannel(req->cid());
            basicResponse(req->cid(), req->rid(), true);
        }
        Channel::ptr getChannel(const std::string& cid)
        {
            return _channels->getChannel(cid);
        }
    private:
        void basicResponse(const std::string& cid, const std::string& rid, bool ret)
        {
            basicCommonResponse resp;
            resp.set_cid(cid);
            resp.set_rid(rid);
            resp.set_ok(ret);
            _codec->send(_conn, resp);
        }   
    private:
        muduo::net::TcpConnectionPtr _conn;
        ChannelManager::ptr _channels;
        VirtualHost::ptr _host;
        ConsumerManager::ptr _cmp;
        ProtobufCodecPtr _codec;
        ThreadPool::ptr _pool;
    };
    class ConnectionManager
    {
    public:
        using ptr = std::shared_ptr<ConnectionManager>;
        void createConnection(const muduo::net::TcpConnectionPtr& conn,
            const VirtualHost::ptr& host,
            const ConsumerManager::ptr& cmp,
            const ProtobufCodecPtr& codec,
            const ThreadPool::ptr& pool)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                if(_connections.find(conn) != _connections.end())
                {
                    return ;
                }
                auto cnp = std::make_shared<Connection>(conn, host, cmp, codec, pool);
                _connections.insert(std::make_pair(conn, cnp));
            }
        void deleteConnection(const muduo::net::TcpConnectionPtr& conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _connections.erase(conn); // 智能指针会在生命周期结束时进行析构
        }
        Connection::ptr getConnection(const muduo::net::TcpConnectionPtr& conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _connections.find(conn);
            if(it == _connections.end())
            {
                return Connection::ptr();
            }
            return it->second;
        }
    private:
        std::mutex _mutex;
        std::unordered_map<muduo::net::TcpConnectionPtr, Connection::ptr> _connections;
    };
}

#endif